package cn.lg.soar.mvc.util;

import cn.lg.soar.core.util.ValidationUtils;
import cn.lg.soar.core.util.easyexcel.converters.LocalDateConverter;
import cn.lg.soar.core.util.easyexcel.converters.LocalDateTimeConverter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 模板导出工具
 * @author luguoxiang
 * @Date: 2023/8/30 10:31
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Valid
public class TemplateExport {

	final static ClassLoader CLASS_LOADER = TemplateExport.class.getClassLoader();

	private final String templatePath;

	private final List<Sheet> sheets;

	private String filename;

	public TemplateExport(@NotBlank(message = "请配置目标路径") String templatePath) {
		this.templatePath = templatePath;
		this.sheets = new ArrayList<>();
	}

	public TemplateExport addSheet(Sheet sheet) {
		sheets.add(sheet);
		return this;
	}

	public TemplateExport addSheet(List<?> list) {
		Sheet sheet = new Sheet();
		sheet.list = list;
		sheets.add(sheet);
		return this;
	}

	public TemplateExport addSheet(Object data) {
		Sheet sheet = new Sheet();
		sheet.data = data;
		sheets.add(sheet);
		return this;
	}

	public TemplateExport addSheet(List<?> list, Object data) {
		Sheet sheet = new Sheet();
		sheet.list = list;
		sheet.data = data;
		sheets.add(sheet);
		return this;
	}

	public TemplateExport setFilename(String filename) {
		this.filename = filename;
		return this;
	}

	/**
	 * 执行导出
	 */
	public void execute() {
		Set<String> errors = ValidationUtils.validateToMsg(this);
		Assert.isTrue(errors.isEmpty(), String.join("；", errors));
		String filename = this.filename;
		if (!StringUtils.hasText(filename)) {
			filename = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
		}
		HttpServletResponse response = ResponseUtils.getResponse();
		try (
				InputStream inputStream = CLASS_LOADER.getResourceAsStream(this.templatePath);
				OutputStream outputStream = response.getOutputStream();
		) {
			ResponseUtils.setResponseExcel(filename, response);
			LocalDateConverter localDateConverter = new LocalDateConverter();
			LocalDateTimeConverter localDateTimeConverter = new LocalDateTimeConverter();
			ExcelWriter excelWriter = EasyExcel
					.write(outputStream)
					.withTemplate(inputStream)
					.registerConverter(localDateConverter)
					.registerConverter(localDateTimeConverter)
					.build();
			FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

			List<Sheet> sheets = this.sheets;
			for (int i = 0, len = sheets.size(); i < len; i++) {
				Sheet sheet = sheets.get(i);
				ExcelWriterSheetBuilder excelWriterSheetBuilder;
				if (sheet.sheetNo != null) {
					excelWriterSheetBuilder = EasyExcel.writerSheet(sheet.sheetNo);
				} else if (sheet.sheetName != null) {
					excelWriterSheetBuilder = EasyExcel.writerSheet(sheet.sheetName);
				} else {
					excelWriterSheetBuilder = EasyExcel.writerSheet(i);
				}
				if (sheet.cellWriteHandler != null) {
					excelWriterSheetBuilder.registerWriteHandler(sheet.cellWriteHandler);
				}
				excelWriterSheetBuilder.registerConverter(localDateConverter);
				excelWriterSheetBuilder.registerConverter(localDateTimeConverter);
				WriteSheet writeSheet = excelWriterSheetBuilder.build();
				if (!CollectionUtils.isEmpty(sheet.list)) {
					excelWriter.fill(sheet.list, fillConfig, writeSheet);
				}
				if (sheet.data != null) {
					excelWriter.fill(sheet.data, writeSheet);
				}
			}
			// 导出
			excelWriter.finish();
		} catch (Exception e){
			throw new RuntimeException(e);
		}
	}

	/**
	 * 创建
	 * @param templatePath
	 * @return
	 */
	public static TemplateExport create(String templatePath) {
		return new TemplateExport(templatePath);
	}

	@Getter
	@Setter
	public static class Sheet {

		private Integer sheetNo;

		private String sheetName;

		private List<?> list;

		private Object data;

		private CellWriteHandler cellWriteHandler;

	}
}
